package cn.yangliu.nacos.oauth2.entity;

import cn.yangliu.nacos.comm.audit.AbstractEntity;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.hibernate.annotations.Type;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.provider.ClientDetails;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * The interface Oauth 2 client.
 *
 * @author 问道于盲
 * @date 2019 -03-26 01:20
 */
@EqualsAndHashCode(callSuper = false)
@Getter
@NoArgsConstructor
@Setter
@Table(name = "oauth2_client")
@ToString
@Entity
public class Oauth2Client extends AbstractEntity implements Serializable, ClientDetails {

    /**
     * current class's static member
     * The constant serialVersionUID.
     */
    private static final long serialVersionUID = 1L;

    /**
     * 应用名称
     */
    @Column(nullable = false, unique = true)
    private String name;

    /**
     * 应用id
     */
    @Column(updatable = false, unique = true, nullable = false)
    private String clientId;

    /**
     * 应用密钥
     */
    @Column(nullable = false)
    private String clientSecret;

    /**
     * 应用描述
     */
    private String description;

    /**
     * 应用icon地址
     */
    private String iconUri;

    /**
     * 应用范围
     */
    @Column(nullable = false)
    private String scopes;

    /**
     * 应用所支持的授权模式,至少一个,多个用逗号隔开
     */
    @Column(nullable = false)
    private String grantTypes;

    /**
     * 认证令牌有效期COMMENT ,单位秒
     */
    @Column(nullable = false)
    private Integer accessTokenValiditySeconds;

    /**
     * 刷新令牌有效期COMMENT ,单位秒
     */
    @Column(nullable = false)
    private Integer refreshTokenValiditySeconds;

    /**
     * 是否受信任的,0,不受信,1受信
     */
    @Column(unique = true)
    @Type(type = "true_false")
    private boolean trusted;

    /**
     * 应用重定向地址
     */
    @Column(length = 1000)
    private String redirectUris;

    /**
     * current class instance's member.
     * The Authorities.
     */
    private String authorities;

    /**
     * current class method for getter.
     * Gets resource ids.
     *
     * @return the resource ids
     */
    @Override
    public Set<String> getResourceIds() {
        return null;
    }

    /**
     * Is secret required boolean.
     *
     * @return the boolean
     */
    @Override
    public boolean isSecretRequired() {
        return true;
    }

    /**
     * Is scoped boolean.
     *
     * @return the boolean
     */
    @Override
    public boolean isScoped() {
        return true;
    }

    /**
     * current class method for getter.
     * Gets scope.
     *
     * @return the scope
     */
    @Override
    public Set<String> getScope() {
        return createSet(scopes);
    }

    /**
     * current class method for getter.
     * Gets authorized grant types.
     *
     * @return the authorized grant types
     */
    @Override
    public Set<String> getAuthorizedGrantTypes() {
        return createSet(grantTypes);
    }

    /**
     * Create set linked hash set.
     *
     * @param s the s
     * @return the linked hash set
     */
    private LinkedHashSet<String> createSet(String s) {
        LinkedHashSet<String> set = new LinkedHashSet<>();
        if (s != null) {
            String[] split = s.split(",");
            set.addAll(Arrays.asList(split));
        }
        return set;
    }


    /**
     * current class method for getter.
     * Gets registered redirect uri.
     *
     * @return the registered redirect uri
     */
    @Override
    public Set<String> getRegisteredRedirectUri() {
        return createSet(redirectUris);
    }

    /**
     * 不能返回null 否则永远不能通过
     * 详情 org.springframework.security.core.userdetails.User#123
     * this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities));
     *
     * @return the authorities
     */
    @Override
    public Collection<GrantedAuthority> getAuthorities() {
        List<GrantedAuthority> authoritiesList = new ArrayList<>();
        if (Objects.isNull(authorities)) {
            return authoritiesList;
        }
        String[] split = authorities.split(",");

        for (String s : split) {
            authoritiesList.add(new SimpleGrantedAuthority(s));
        }
        return authoritiesList;
    }


    /**
     * Is auto approve boolean.
     *
     * @param scope the scope
     * @return the boolean
     */
    @Override
    public boolean isAutoApprove(String scope) {
        return false;
    }

    /**
     * current class method for getter.
     * Gets additional information.
     *
     * @return the additional information
     */
    @Override
    public Map<String, Object> getAdditionalInformation() {
        Map<String, Object> info = new HashMap<>(10);
        if (name != null) {
            info.put("name", name);
        }
        if (description != null) {
            info.put("desp", description);
        }
        if (iconUri != null) {
            info.put("icon_uri", iconUri);
        }
        return info;
    }
}
